package com.yxb.service.server.interfimpl;

import com.allen.page.DataPage;
import com.yxb.constant.DataPointValue;
import com.yxb.constant.SendMsgEvent;
import com.yxb.option.DataPoint;
import com.yxb.option.DeviceInfoVo;
import com.yxb.service.common.domain.DeviceData;
import com.yxb.service.common.domain.UserDevice;
import com.yxb.service.common.interf.DeviceDataService;
import com.yxb.service.common.option.DeviceDataOption;
import com.yxb.service.server.manager.DeviceDataManager;
import com.yxb.service.server.manager.UserDeviceManager;
import com.yxb.thirdsdk.push.JpushService;
import com.yxb.util.LocalDateTimeUtil;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.tuple.ImmutablePair;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.math.MathContext;
import java.math.RoundingMode;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;


/**
 * @author
 */
@Service
public class DeviceDataServiceImpl implements DeviceDataService {

    private static final Logger LOGGER = LoggerFactory.getLogger(DeviceDataServiceImpl.class);

    private static final String DATA_POINT_TYPE =  "bytearray";

    private volatile Map<String, Object>  cacheKeyMap = new ConcurrentHashMap<>();

    private static String ALERT_MSG = "有一次体重Xkg的测量";


    @Resource
    private DeviceDataManager deviceDataManager;

    @Resource
    private UserDeviceManager  userDeviceManager;

    @Resource
    private JpushService jpushService;

    @Resource
    private ThreadPoolTaskExecutor taskExecutor;

    @Override
    public ImmutablePair<Boolean,String> userAccept(Integer userId, Integer dId) {
        DeviceData deviceData = deviceDataManager.queryOne(dId);
        if (deviceData == null ){
            LOGGER.error("dId:[{}], not found data", dId);
            return ImmutablePair.of(Boolean.FALSE, "找不到设备信息");
        }

        if ( deviceData.getIsAccept() ){
            LOGGER.error("dId:[{}], data is accept by [{}] at [{}]", deviceData.getAcceptUserId(),
                    LocalDateTimeUtil.DEFAULT_FORMATTER.format(deviceData.getAcceptTime()));
            return ImmutablePair.of(Boolean.FALSE, "设备信息已经被认领了");
        }

        deviceData.setAcceptUserId(String.valueOf(userId));
        deviceData.setAcceptTime(LocalDateTime.now());
        deviceData.setIsAccept(Boolean.TRUE);
        boolean success = deviceDataManager.updateByAccept(deviceData);
        return success ? ImmutablePair.of(Boolean.TRUE, "") : ImmutablePair.of(Boolean.FALSE, "认领错误");
    }


    @Override
    public DataPage<DeviceData> queryPage(DataPage<DeviceData> dataPage, DeviceDataOption option, Integer userId) {
        option.setAcceptUserId(String.valueOf(userId));
        return deviceDataManager.queryPage(dataPage, option);
    }

    @Override
    public DataPage<DeviceData> queryPage(DataPage<DeviceData> dataPage, DeviceDataOption option, String deviceId) {
        option.setDeviceId(deviceId);
        return deviceDataManager.queryPage(dataPage, option);
    }

    @Override
    public DataPage<DeviceData> queryDevicePage(DataPage<DeviceData> dataPage, DeviceDataOption option) {
        return deviceDataManager.queryDevicePage(dataPage, option);
    }

    @Override
    public List<DeviceData> queryList(DeviceDataOption option) {
        return deviceDataManager.queryList(option);
    }

    @Override
    public ImmutablePair<Boolean, String> addObject(DeviceInfoVo deviceInfoVo) {

        if ( deviceInfoVo.getType().equalsIgnoreCase(SendMsgEvent.SYNC ) ){
            List<DataPoint> pointList = deviceInfoVo.getDatapoint() ;
            if ( pointList == null || pointList.isEmpty() ){
                return ImmutablePair.of(Boolean.FALSE, "数据为空");
            }
            DeviceData deviceData = createDeviceData(deviceInfoVo);

            List<DataPoint> dataPointList =  deviceInfoVo.getDatapoint();

            if ( dataPointList != null && !dataPointList.isEmpty()){
                LOGGER.info("datapoint :{} 条数据", dataPointList.size());
                List<String> valueList = dataPointList.stream()
                        .filter(p-> DATA_POINT_TYPE.equalsIgnoreCase(p.getType()))
                        .sorted(Comparator.comparingInt(DataPoint::getIndex))
                        .map(m->m.getValue())
                        .collect(Collectors.toList());

                if ( valueList != null && !valueList.isEmpty() ){
                    String value = valueList.get(0);
                    DataPointValue dataPointValue  =  DataPointValue.parseStrValue(value);
                    deviceData.setMsgCreatedTime(LocalDateTimeUtil.getFromEpochSecond(dataPointValue.getUtc()));
                    BigDecimal   weight =  new BigDecimal(String.valueOf(dataPointValue.getWeight()));
                    deviceData.setWeight( weight.divide(new BigDecimal("20"), 2, RoundingMode.HALF_EVEN));
                    deviceData.setBodyFat(new BigDecimal(""+dataPointValue.getImpedance()));
                    if (StringUtils.isNotBlank(deviceData.getDeviceProductId()) && StringUtils.isNotBlank(deviceData.getDeviceId())
                            && dataPointValue.getUtc()>0){

                        String cacheKey = deviceData.getDeviceProductId()+":"+deviceData.getDeviceId()+":"+dataPointValue.getUtc();
                        if ( cacheKeyMap.containsKey(cacheKey) ){
                            LOGGER.info("cacheKey:[{}],正在处理中", cacheKey);
                            return ImmutablePair.of(Boolean.FALSE, "数据正在处理");
                        }
                        cacheKeyMap.put(cacheKey, 1);

                        try {
                            DeviceDataOption option = new DeviceDataOption();
                            option.setDeviceProductId(deviceData.getDeviceProductId());
                            option.setDeviceId(deviceData.getDeviceId());
                            option.setMsgCreatedTime(deviceData.getMsgCreatedTime());
                            List<DeviceData> deviceDataList =  deviceDataManager.queryList(option);
                            if ( deviceDataList == null ||  deviceDataList.isEmpty() ){
                                boolean success = deviceDataManager.addObject(deviceData);
                                if( success ){
                                    taskExecutor.execute(()->{
                                        try{
                                            UserDevice userDevice = userDeviceManager.queryByDeviceId(deviceData.getDeviceId(), Boolean.TRUE);
                                            if ( userDevice !=null ){
                                                jpushService.sendMsg(userDevice.getUserId(), ALERT_MSG.replace("X", weight.toPlainString()));
                                            } else {
                                                LOGGER.info("根据设备ID查询不到绑定的设备信息:{}", deviceData.getDeviceId());
                                            }
                                        } catch (RuntimeException e){
                                            LOGGER.info("发送推送信息异常:{}", e);
                                        }
                                    });
                                    return ImmutablePair.of(Boolean.TRUE, "数据保存成功");
                                }
                            }
                            LOGGER.info("cacheKey:[{}],数据已经存在了", cacheKey);
                            return ImmutablePair.of(Boolean.FALSE, "数据已经存在了");
                        } catch (RuntimeException e){
                            LOGGER.info("add device data runtimeException" , e);
                        } finally {
                            cacheKeyMap.remove(cacheKey);
                        }
                    }
                }
            }

            LOGGER.info("add device_data_info ->{}", deviceData.toString());
            boolean success = deviceDataManager.addObject(deviceData);
            if( success ){
                LOGGER.info("no dataPoint data save success");
                return ImmutablePair.of(Boolean.TRUE, "数据保存成功");
            }
            LOGGER.info("no dataPoint data save fail");
            return ImmutablePair.of(Boolean.FALSE, "数据保存失败");
        }

        return ImmutablePair.of(Boolean.FALSE, "消息类型不是SYNC");
    }

    private DeviceData createDeviceData(DeviceInfoVo deviceInfoVo){
        DeviceData deviceData = new DeviceData();
        deviceData.setDeviceProductId(deviceInfoVo.getProduct_id());
        deviceData.setDeviceId(String.valueOf(deviceInfoVo.getFrom_id()));
        deviceData.setMsgId(deviceInfoVo.getMsg_id());
        deviceData.setIsAccept(Boolean.FALSE);
        deviceData.setReportTime(LocalDateTime.now());
        return deviceData;
    }

    public static void main(String[] args) {
        int i = 1200;
        System.out.println(new BigDecimal(String.valueOf(i/20), new MathContext(1)).toPlainString());
        Instant instant = Instant.ofEpochSecond(1522828079);
        LocalDateTime time =  LocalDateTime.ofInstant(instant, ZoneId.systemDefault() );

        System.out.println(time);
    }

}
